<?php

namespace app\web\service;

use app\common\logic\CommonLogic;
use app\common\logic\OrderLogic;
use app\common\logic\PayLogic;
use app\common\model\commonModel;
use app\common\model\trCar;
use app\common\model\trOrder;
use app\common\model\trOrderOutletsDetail;
use app\common\model\trOutletsAgreement;
use app\common\model\trOutletsCar;
use app\common\model\trOutletsSearch;
use app\common\model\trOutletsSurcharge;
use app\common\model\trRentalOutlets;
use app\common\model\trResource;
use app\common\model\trUser;
use app\common\util\ErrorCode;
use app\common\util\GeoTransUtil;
use app\common\util\Tools;
use app\common\util\WxPay;

/**
 * Class OutletsService
 * @package app\admin\service
 */
class OutletsService extends BaseService
{
    public function getList(){
        $data = trRentalOutlets::where(["mall_id" => $this->mall_id, "status" => 1])
            ->field("id,name,province_code,city_code,area_code,address")
            ->select()->toArray();
        $data = $this->convertData($data);
        foreach ($data as &$item) {
            $address = Tools::getNameByPCA($item["provinceCode"], $item["cityCode"], $item["areaCode"]);
            $item["address"] = str_replace(" ", "", $address) . $item["address"];
            unset($item["provinceCode"], $item["cityCode"], $item["areaCode"]);
        }
        unset($item);
        $this->returnData["data"] = $data;
        return $this->returnData;
    }

    public function getSearchData(){
        $content = trOutletsSearch::where(["mall_id" => $this->mall_id, "user_id" => request()->userLoginData["id"]])->value("content");
        $this->returnData["data"] = @json_decode($content, true);
        return $this->returnData;
    }

    public function getInfo(){
        if(empty($this->params["id"])){
            return ErrorCode::code("params_not_exist", "id");
        }
        $data = trRentalOutlets::where(["id" => $this->params["id"], "mall_id" => $this->mall_id])->find();
        if(empty($data)){
            return ErrorCode::code("customized", "数据不存在");
        }
        $data = $this->convertData($data->toArray());
        $address = Tools::getNameByPCA($data["provinceCode"], $data["cityCode"], $data["areaCode"]);
        $data["address"] = str_replace(" ", "", $address).$data["address"];
        $data['picId'] = explode(",", $data["picId"]);
        foreach ($data["picId"] as $pic){
            $data['picUrl'][] = [
                "url" => tome_dia(trResource::getValue("url", ["id" => $pic])),
                "id" => $pic
            ];
        }
        $this->returnData["data"] = $data;
        return $this->returnData;
    }

    public function searchOutlets(){
        if(empty($this->params["longitude"])){
            return ErrorCode::code("params_not_exist", "经度");
        }
        if(empty($this->params["latitude"])){
            return ErrorCode::code("params_not_exist", "纬度");
        }
        $db = trRentalOutlets::where(["mall_id" => $this->params["mallId"], "status" => 1]);
        if(!empty($this->params["searchValue"])){
            $res = CommonLogic::getLatLon($this->params["searchValue"]);
            if($res){
                $res["lng"] = substr($res["lng"], 0, strpos($res["lng"], ".")+3);
                $res["lat"] = substr($res["lat"], 0, strpos($res["lat"], ".")+3);
                $db->where([["longitude", "like", "{$res["lng"]}%"], ["latitude", "like", "{$res["lat"]}%"]]);
            }
            if(!empty($this->params["token"])) {
                $userLogin = LoginService::checkToken($this->params["token"]);
                if(!empty($userLogin["id"])){
                    $content = trOutletsSearch::where(["mall_id" => $this->mall_id, "user_id" => $userLogin["id"]])->value("content");
                    if(!empty($content)) {
                        $content = (array)@json_decode($content, true);
                        if (count($content) >= 5) {
                            array_pop($content);
                        }
                        if(!in_array($this->params["searchValue"], $content))
                            array_unshift($content, $this->params["searchValue"]);
                        trOutletsSearch::where(["mall_id" => $this->mall_id, "user_id" => $userLogin["id"]])
                            ->update(["content" => json_encode($content, JSON_UNESCAPED_UNICODE)]);
                    }else{
                        trOutletsSearch::create([
                            "mall_id" => $this->mall_id, "user_id" => $userLogin["id"],
                            "content" => json_encode([$this->params["searchValue"]], JSON_UNESCAPED_UNICODE)
                        ]);
                    }
                }
            }
        }
        $database = $db->with(["carList" => function($query){
            $query->where("status", 1);
        }])->select();
        $data = $this->convertData($database->toArray());
        /** @var trRentalOutlets $item */
        foreach ($database as $k => $item){
            /** @var trOutletsCar $car */
            foreach ($item->carList as $s => $car){
                if($car->over_stock == 0){
                    unset($data[$k]);
                    continue;
                }
                $data[$k]["carList"][$s]["price"] = floatval($car->price);
                $data[$k]["carList"][$s]["name"] = $car->car->name;
                $data[$k]["carList"][$s]["seat"] = $car->car->seat;
                $data[$k]["carList"][$s]["icon"] = tome_dia(trResource::getValue("url", ["id" => $car->car->icon]));
                $data[$k]["carList"][$s]["modelNumber"] = $car->car->model_number;
                $data[$k]["carList"][$s]["carType"] = $car->car->type == 1 ? "燃油" : ($car->car->type == 2 ? "电动" : "混动"); // 1燃油，2电动，3混动
            }
            if(empty($data[$k]["carList"])){
                unset($data[$k]);
                continue;
            }
            $data[$k]["distanceNum"] = GeoTransUtil::get_distance($item["longitude"], $item["latitude"], $this->params["longitude"], $this->params["latitude"], 2, 1);
            $data[$k]["distance"] = $data[$k]["distanceNum"]."km";
        }
        if(!empty($data)) {
            array_multisort(array_column($data, "distanceNum"), SORT_ASC, $data);
        }
        $this->returnData["data"] = $data;
        return $this->returnData;
    }

    public function getPriceCalendar(){
        if(empty($this->params["id"])){
            return ErrorCode::code("params_not_exist", "id");
        }
        if(empty($this->params["date"])){
            return ErrorCode::code("params_not_exist", "时间");
        }
        $database = trOutletsCar::where("id", $this->params["id"])->field("week_price,special_price")->find();
        if(empty($database)){
            return ErrorCode::code("customized", "数据不存在");
        }
        $weekPrice = explode(",", $database->week_price);
        $specialPrice = (array)@json_decode($database->special_price, true);
        if(empty($weekPrice) && empty($specialPrice)){
            return ErrorCode::code("customized", "该车辆未设置价格");
        }
        if(!empty($specialPrice)){
            $specialPrice = array_column($specialPrice, "price", "date");
        }
        $start = strtotime($this->params["date"]); // 开始时间戳
        $end = strtotime(date("Y-m-t 23:59:59", $start)); // 结束时间戳
        $data = [];
        do{
            $time = date("Y-m-d", $start);
            if(isset($specialPrice[$time])){
                $data[] = floatval($specialPrice[$time]);
            }else{
                $w = date("w", $start);
                $data[] = floatval(!empty($weekPrice[$w]) ? $weekPrice[$w] : "0");
            }
            $start += 86400;
        }while($end >= $start);
        $this->returnData["data"] = $data;
        return $this->returnData;
    }

    public function getAgreement(){
        if(empty($this->params["id"])){
            return ErrorCode::code("params_not_exist", "id");
        }
        $data = trOutletsAgreement::where("id", $this->params["id"])->field("name,content")->find();
        if(empty($data)){
            $data = ["name" => "", "content" => ""];
        }else{
            $data = $data->toArray();
        }
        $this->returnData["data"] = $data;
        return $this->returnData;
    }

    public function prepareOrder(){
        $field = [
            "takeOutletId" => "取车网点id", "ocId" => "网点车id", "startTime" => "开始时间", "endTime" => "结束时间"
        ];
        foreach ($field as $k => $v) {
            if(!isset($this->params[$k])){
                return ErrorCode::code('params_not_exist', $v);
            }
        }
        if($this->params["startTime"] > $this->params["endTime"]){
            return ErrorCode::code("params_error", "时间");
        }
        $database = trRentalOutlets::alias("o")
            ->leftJoin(trOutletsCar::getTable()." c", "o.id=c.outlet_id")
            ->leftJoin(trCar::getTable()." ct", "ct.id=c.car_id")
            ->field([
                "c.week_price", "c.special_price", "o.name", "ct.icon", "ct.name as carName",
                "ct.remark", "c.over_stock", "ct.model_number", "ct.type"
            ])
            ->where(["o.id" => $this->params["takeOutletId"], "c.id" => $this->params["ocId"]])
            ->find();
        if(empty($database)){
            return ErrorCode::code("customized", "数据不存在");
        }
        $weekPrice = explode(",", $database->week_price);
        $specialPrice = (array)@json_decode($database->special_price, true);
        if(empty($weekPrice) && empty($specialPrice)){
            return ErrorCode::code("customized", "车辆未设置价格");
        }
        if($database->over_stock <= 0){
            return ErrorCode::code("customized", "车辆库存不足");
        }
        if(!empty($specialPrice)){
            $specialPrice = array_column($specialPrice, "price", "date");
        }
        $start = strtotime($this->params['startTime']); // 开始时间戳
        $end = strtotime($this->params['endTime']); // 结束时间戳
        $price = 0;
        $day = 0;
        do{
            $time = date("Y-m-d", $start);
            if(isset($specialPrice[$time])){
                $price += $specialPrice[$time];
            }else{
                $w = date("w", $start);
                $price += (!empty($weekPrice[$w]) ? $weekPrice[$w] : 0);
            }
            $start += 86400;
            $day++;
        }while($end >= $start);
        $data = [
            "takeOutletName" => $database->name, "carName" => $database->carName,
            "carIcon" => tome_dia(trResource::getValue("url", ["id" => $database->icon])),
            "carType" => $database->type == 1 ? "燃油" : ($database->type == 2 ? "电动" : "混动"),
            "carRemark" => $database->remark, "optionalServe" => [], "modelNumber" => $database->model_number,
            "startTime" => date("Y年m月d日", strtotime($this->params['startTime'])),
            "endTime" => date("Y年m月d日", strtotime($this->params['endTime'])),
            "totalDay" => $day, "mustServe" => [
                ["id" => 0, "name" => "车辆租凭及服务费", "price" => number_format($price, 2, ".", ""), "desc" => ""]
            ],
        ];
        $surchargeData = trOutletsSurcharge::where(["mall_id" => $this->mall_id, "status" => 1])->select()->toArray();
        foreach ($surchargeData as $item){
            if($item["mode"] == '1'){ // 默认
                $price += $item["price"];
                $data["mustServe"][] = ["id" => $item["id"], "name" => $item["name"], "price" => number_format($item["price"], 2, ".", ""), "desc" => $item["desc"]];
            }else{
                $data["optionalServe"][] = ["id" => $item["id"], "name" => $item["name"], "price" => number_format($item["price"], 2, ".", ""), "desc" => $item["desc"]];
            }
        }
        $data["agreement"] = trOutletsAgreement::where(["mall_id" => $this->mall_id, "status" => 1])
            ->field("id,name")
            ->select()->toArray();
        $data["carPrice"] = number_format($price, 2, ".", "");
        if(empty($this->params["alsoOutletId"]) || $this->params["takeOutletId"] == $this->params["alsoOutletId"]){
            $data["alsoOutletName"] = $data["takeOutletName"];
        }else{
            $data["alsoOutletName"] = trRentalOutlets::where("id", $this->params["alsoOutletId"])->value("name");
        }
        $this->returnData["data"] = $data;
        return $this->returnData;
    }

    public function submitOrder(){
        $field = [
            "takeOutletId" => "取车网点id", "ocId" => "网点车id", "startTime" => "开始时间", "endTime" => "结束时间"
        ];
        foreach ($field as $k => $v) {
            if(!isset($this->params[$k])){
                return ErrorCode::code('params_not_exist', $v);
            }
        }
        if($this->params["startTime"] > $this->params["endTime"]){
            return ErrorCode::code("params_error", "时间");
        }
        $database = trRentalOutlets::alias("o")
            ->leftJoin(trOutletsCar::getTable()." c", "o.id=c.outlet_id")
            ->leftJoin(trCar::getTable()." ct", "ct.id=c.car_id")
            ->field(["c.week_price", "c.special_price", "o.name", "c.over_stock"])
            ->where(["o.id" => $this->params["takeOutletId"], "c.id" => $this->params["ocId"]])
            ->find();
        if(empty($database)){
            return ErrorCode::code("customized", "数据不存在");
        }
        $weekPrice = explode(",", $database->week_price);
        $specialPrice = (array)@json_decode($database->special_price, true);
        if(empty($weekPrice) && empty($specialPrice)){
            return ErrorCode::code("customized", "车辆未设置价格");
        }
        if($database->over_stock <= 0){
            return ErrorCode::code("customized", "车辆库存不足");
        }
        if(!empty($specialPrice)){
            $specialPrice = array_column($specialPrice, "price", "date");
        }
        $start = strtotime($this->params['startTime']); // 开始时间戳
        $end = strtotime($this->params['endTime']); // 结束时间戳
        $price = 0;
        do{
            $time = date("Y-m-d", $start);
            if(isset($specialPrice[$time])){
                $price += $specialPrice[$time];
            }else{
                $w = date("w", $start);
                $price += (!empty($weekPrice[$w]) ? $weekPrice[$w] : 0);
            }
            $start += 86400;
        }while($end >= $start);
        $detail = [
            "take_id" => $this->params["takeOutletId"], "oc_id" => $this->params["ocId"],
            "start_time" => $this->params['startTime'], "end_time" => $this->params['endTime'], "serve" => [
                ["id" => 0, "name" => "车辆租凭及服务费", "price" => floatval($price)]
            ]
        ];
        $optionalServe = !empty($this->params["optionalServe"]) ? explode(",", $this->params["optionalServe"]) : [];
        $surchargeData = trOutletsSurcharge::where(["mall_id" => $this->mall_id, "status" => 1])->select()->toArray();
        foreach ($surchargeData as $item){
            if($item["mode"] == '1' || in_array($item["id"], $optionalServe)){ // 默认
                $price += $item["price"];
                $detail["serve"][] = ["id" => $item["id"], "name" => $item["name"], "price" => floatval($item["price"])];
            }
        }
        $couponAmount = 0;      // 优惠金额
        $userCouponId = 0;     //优惠券id
        if(!empty($this->params['userCouponId']) && !empty($couponInfo = commonModel::getFields(userCouponTable,'amount',['id' => $this->params['userCouponId']]))){
            $userCouponId = $this->params['userCouponId'];
            $couponAmount = $couponInfo['amount'];
        }
        $orderModel = new trOrder();
        $orderSn = $orderModel->getSn();
        $paymentNo = $orderModel->getPayNo();
        $userData = trUser::where("id", request()->userLoginData["id"])->field("id,nickname,mobile,openid")->find();
        $orderData = [
            "order_sn" => $orderSn,
            "mall_id" => $this->mall_id,
            "user_id" => $userData->id,
            "contact_name" => $userData->nickname,
            "mobile" => $userData->mobile,
            "total_money" => $price,  // 订单总价格
            "pay_money" => $price > $couponAmount ? $price - $couponAmount : 0,  // 去支付的价格
            "discount_money" => $couponAmount, // 没接优惠券，所有默认0
            "commission" => 0,
            "coupon_id" => $userCouponId,    //新 用户优惠券表 id
            "reserve_time" => $this->params['startTime'] . " " . $this->params['endTime'], // 时间
            "type" => 5,   //类型；1机场接送，2巴士路线，3专车接送，4包车路线, 5租车网点
            "payment_no" => $paymentNo,
            "memo" => isset($this->params["memo"]) ? $this->params["memo"] : "",
            "address_from" => $database->name,
        ];
        $detail["serve"] = json_encode($detail["serve"], JSON_UNESCAPED_UNICODE);
        if(empty($this->params["alsoOutletId"]) || $this->params["takeOutletId"] == $this->params["alsoOutletId"]){
            $orderData["address_to"] = $database->name;
            $detail["also_id"] = $this->params["takeOutletId"];
        }else{
            $orderData["address_to"] = trRentalOutlets::where("id", $this->params["alsoOutletId"])->value("name");
            $detail["also_id"] = $this->params["alsoOutletId"];
        }
        if($orderId = $orderModel->add($orderData, true)){
            $detail["order_id"] = $orderId;
            trOrderOutletsDetail::create($detail);
            //订单后续操作
            if($orderData["pay_money"]) {
                $data = ["total_fee" => $orderData["pay_money"] * 100, "openid" => $userData->openid, "out_trade_no" => $paymentNo, "body" => "租车支付"];
                // 加的测试
                if (in_array(request()->host(), ["cardemo.wegouer.com/test/cars-pai", "service-emhatyrq-1251017581.gz.apigw.tencentcs.com/test/cars-pai"])) {
                    $data["total_fee"] = 1; // 测试 1毛
                }
                $wxPay = new WxPay();
                $res = $wxPay->toPay($data); // 获取支付信息
                if (isset($res["code"])) {
                    $this->returnData = $res;
                } else {
                    // 订单有效时间为30分钟，时间一到就要自动取消
                    OrderLogic::cancelOrderJobs($orderSn, ["orderSn" => $orderSn, "userId" => $userData->id]);
                    $res["orderSn"] = $orderSn;
                    $this->returnData["data"] = $res;
                }
            }else{
                $payLogic = new PayLogic();
                $userModel = new trUser();
                $payLogic->updateOrder($paymentNo, ["tradeNo" => "", "totalFee" => 0, "payAccount" => $userModel->getValue("nickname", ["id" => $userData->id])]);
                $this->returnData["data"] = ["orderSn" => $orderSn];
            }
        }else{
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "生成订单失败";
        }
        return $this->returnData;
    }
}